import tkinter as tk
from tkinter import ttk, messagebox
import json
import os
import random
import shutil
import sys
from hanzi_data2 import HANZI_DATA, PINYIN_MAP

CONFIG_FILE = 'user_config.json'

class ChineseLearningApp:
    def __init__(self, master):
        self.master = master
        self.master.title("小学生学汉字")
        
        # 加载用户配置
        self.load_config()
        
        # 创建主界面
        self.create_main_interface()
        
        # 窗口居中设置（移至界面创建后）
        self.master.after(100, self.center_window)  # 延迟二次居中

    def center_window(self):
        self.master.update_idletasks()
        screen_width = self.master.winfo_screenwidth()
        screen_height = self.master.winfo_screenheight()
        window_width = self.master.winfo_reqwidth()
        window_height = self.master.winfo_reqheight()
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2
        self.master.geometry(f"+{x}+{y}")

    def center_pinyin_window(self):
        self.learning_window.update_idletasks()
        screen_width = self.learning_window.winfo_screenwidth()
        screen_height = self.learning_window.winfo_screenheight()
        window_width = self.learning_window.winfo_reqwidth()
        window_height = self.learning_window.winfo_reqheight()
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2
        self.learning_window.geometry(f"+{x}+{y}")

    def load_config(self):
        try:
            if os.path.exists(CONFIG_FILE):
                # 备份旧配置文件
                backup_path = f'{CONFIG_FILE}.bak'
                if os.path.exists(backup_path):
                    os.remove(backup_path)
                shutil.copy(CONFIG_FILE, backup_path)

                # 尝试多种编码方式读取
                try:
                    with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
                        self.config = json.load(f)
                except UnicodeDecodeError:
                    with open(CONFIG_FILE, 'r', encoding='gbk') as f:
                        self.config = json.load(f)

                # 验证配置完整性
                if 'last_grade' not in self.config or 'last_unit' not in self.config:
                    raise ValueError("配置文件不完整")
                # 确保旧版本配置文件兼容
                if 'history_records' not in self.config:
                    self.config['history_records'] = []

                # 立即用正确编码重写配置文件
                with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
                    json.dump(self.config, f, ensure_ascii=False, indent=2)
            else:
                self.config = {
                    'last_grade': '一年级',
                    'last_unit': '上册-识字1',
                    'history_records': []
                }
        except (json.JSONDecodeError, PermissionError) as e:
            messagebox.showwarning("配置错误", 
                f"配置文件损坏或无法访问:\n{str(e)}\n已创建新配置文件，旧配置备份在 {CONFIG_FILE}.bak")
            self.config = {
                'last_grade': '一年级',
                'last_unit': '上册-识字1',
                'history_records': []
            }
            with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
                json.dump(self.config, f, ensure_ascii=False, indent=2)
        except Exception as e:
            messagebox.showerror("严重错误", 
                f"无法加载配置:\n{str(e)}\n程序将退出")
            sys.exit(1)

    def save_config(self):
        try:
            with open(CONFIG_FILE, 'w', encoding='utf-8') as f:  # 添加编码参数
                json.dump(self.config, f, ensure_ascii=False, indent=2)
        except Exception as e:
            messagebox.showerror("配置错误", f"无法保存配置:\n{str(e)}")

    def on_close(self):
        self.save_config()
        self.master.destroy()

    def create_main_interface(self):
        # 年级选择
        ttk.Label(self.master, text="选择年级:", font=('Microsoft YaHei', 24)).grid(row=0, column=0, padx=20, pady=20)
        self.grade_var = tk.StringVar(value=self.config['last_grade'])
        self.grade_combobox = ttk.Combobox(self.master, values=list(HANZI_DATA.keys()), textvariable=self.grade_var, font=('Microsoft YaHei', 24))
        self.grade_combobox.grid(row=0, column=1, padx=20, pady=20)

        # 单元选择
        ttk.Label(self.master, text="选择单元:", font=('Microsoft YaHei', 24)).grid(row=1, column=0, padx=20, pady=20)
        self.unit_var = tk.StringVar(value=self.config['last_unit'])
        self.unit_combobox = ttk.Combobox(self.master, font=('Microsoft YaHei', 24))
        self.unit_combobox.grid(row=1, column=1, padx=20, pady=20)
        # 初始化单元选项
        self.update_unit_options()
        # 设置保存的单元值
        if self.config['last_unit'] in self.unit_combobox['values']:
            self.unit_combobox.set(self.config['last_unit'])

        # 开始学习按钮
        start_btn = ttk.Button(self.master, text="开始学习", command=self.start_learning, style='Big.TButton')
        start_btn.grid(row=2, column=0, columnspan=2, pady=20)
        
        # 添加历史记录按钮
        history_btn = ttk.Button(self.master, text="查看历史记录", command=self.show_history, style='Medium.TButton')
        history_btn.grid(row=3, column=0, columnspan=2, pady=20)
        
        # 添加按钮样式
        style = ttk.Style()
        style.configure('Big.TButton', font=('Microsoft YaHei', 32), padding=10)
        style.configure('Medium.TButton', font=('Microsoft YaHei', 24), padding=8)

        # 绑定事件
        self.grade_combobox.bind('<<ComboboxSelected>>', lambda e: [self.update_unit_options(), self.save_config()])
        self.unit_combobox.bind('<<ComboboxSelected>>', lambda e: self.save_config())
        self.master.protocol("WM_DELETE_WINDOW", self.on_close)

    def update_unit_options(self):
        grade = self.grade_var.get()
        semester_data = HANZI_DATA.get(grade, {})
        units = [f"{sem}-{unit}" for sem in semester_data for unit in semester_data[sem]]
        self.unit_combobox['values'] = units
        if not self.unit_combobox.get():
            self.unit_combobox.set(units[0] if units else "")

    def start_learning(self):
        # 保存当前选择
        self.config['last_grade'] = self.grade_var.get()
        self.config['last_unit'] = self.unit_combobox.get()
        self.save_config()

        # 隐藏主窗口并创建学习窗口
        self.master.withdraw()
        self.create_pinyin_interface()

    def create_pinyin_interface(self):
        # 创建新窗口
        # 设置窗口尺寸为屏幕1/4的正方形
        screen_width = self.master.winfo_screenwidth()
        screen_height = self.master.winfo_screenheight()
        size = int(min(screen_width, screen_height) * 0.5)
        self.learning_window = tk.Toplevel(self.master)
        self.learning_window.title("拼音练习")
        self.learning_window.protocol("WM_DELETE_WINDOW", self.on_learning_window_close)
        self.learning_window.geometry(f"{int(size*1.5)}x{size}")
        self.learning_window.after(100, self.center_pinyin_window)
        
        # 初始化练习相关变量
        self.score = 0
        self.current_question = 0
        grade = self.config['last_grade']
        sem, unit = self.unit_combobox.get().split('-')
        hanzi_list = HANZI_DATA[grade][sem][unit]
        self.total_questions = len(hanzi_list)
        
        # 创建主框架容器
        main_frame = ttk.Frame(self.learning_window)
        main_frame.grid(row=0, column=0, sticky='nsew')
        
        # 配置根窗口弹性布局
        self.learning_window.rowconfigure(0, weight=1)
        self.learning_window.columnconfigure(0, weight=1)
        
        # 配置主框架网格布局
        main_frame.columnconfigure(0, weight=1)
        main_frame.rowconfigure(0, weight=0)  # 固定顶部高度
        main_frame.rowconfigure(1, weight=1)  # 中间区域自动扩展
        main_frame.rowconfigure(2, weight=0)  # 固定底部高度
        
        # 创建界面元素（放大字体2倍）
        big_font = ('Microsoft YaHei', 36)
        big_font_hanzi = ('Microsoft YaHei', 48)

        # 配置按钮样式
        colors = ['#FFB6C1', '#87CEFA', '#98FB98', '#DDA0DD']
        self.question_label = ttk.Label(main_frame, font=big_font, anchor='center')
        self.question_label.grid(row=0, column=0, sticky='n', pady=20, ipady=10)
        
        # 分拆题目标签为三个部分
        # 创建题目标签容器
        question_frame = ttk.Frame(main_frame)
        question_frame.grid(row=0, column=0, sticky='nsew', pady=20)
        
        # 配置题目标签容器权重
        main_frame.rowconfigure(0, weight=0)
        main_frame.columnconfigure(0, weight=1)
        
        # 添加题目标签组件
        ttk.Label(question_frame, text="请选择 '", font=big_font).grid(row=0, column=0, sticky='e')
        self.hanzi_label = ttk.Label(question_frame, text="", font=big_font_hanzi, foreground='red')
        self.hanzi_label.grid(row=0, column=1)
        ttk.Label(question_frame, text="' 的正确拼音", font=big_font).grid(row=0, column=2, sticky='w')
        
        # 配置标签容器居中
        question_frame.columnconfigure(0, weight=2)
        question_frame.columnconfigure(1, weight=1)
        question_frame.columnconfigure(2, weight=2)
        question_frame.grid_propagate(False)
        
        # 创建选项按钮容器
        options_frame = ttk.Frame(main_frame)
        options_frame.grid(row=1, column=0, sticky='nsew', padx=20, pady=(0,20))
        
        # 配置按钮容器网格
        options_frame.columnconfigure(0, weight=1)
        options_frame.columnconfigure(1, weight=1)
        options_frame.rowconfigure(0, weight=1)
        options_frame.rowconfigure(1, weight=1)
        
        self.option_buttons = []
        btn_size = (300, 280)
        for i in range(4):
            frame = tk.Frame(options_frame, 
                           bg=colors[i], 
                           highlightbackground='#000000', 
                           highlightthickness=5,
                           width=btn_size[0],
                           height=btn_size[1])
            frame.grid_propagate(False)
            frame.grid(row=i//2, column=i%2, padx=15, pady=15, sticky='nsew')
            btn = tk.Button(frame, 
                          command=lambda idx=i: self.check_answer(idx),
                          font=('Microsoft YaHei', 40),
                          bg=colors[i],
                          fg='black',
                          borderwidth=0,
                          relief='flat',
                          width=8,
                          height=3)
            btn.pack(expand=True, fill='both', ipadx=20, ipady=50, anchor='center')
            self.option_buttons.append(btn)
        
        # 得分显示
        self.score_label = ttk.Label(main_frame, text="得分: 0", font=('Microsoft YaHei', 32), anchor='center')
        self.score_label.grid(row=2, column=0, sticky='s', pady=20, ipady=10)
        
        # 开始第一题
        self.next_question()

    def next_question(self):
        # 获取当前选择的单元汉字
        grade = self.config['last_grade']
        sem, unit = self.unit_combobox.get().split('-')
        hanzi_list = HANZI_DATA[grade][sem][unit]
        total_questions = len(hanzi_list)
        if self.current_question >= total_questions:
            self.show_final_result()
            return

        # 初始化已选汉字记录
        if not hasattr(self, 'used_hanzi') or not self.used_hanzi:
            self.used_hanzi = set()
        
        # 获取当前选择的单元汉字
        grade = self.config['last_grade']
        sem, unit = self.unit_combobox.get().split('-')
        hanzi_list = HANZI_DATA[grade][sem][unit]
        
        # 从未使用的汉字中随机选择
        available_hanzi = [h for h in hanzi_list if h not in self.used_hanzi]
        
        # 当所有汉字都已使用时自动重置
        if not available_hanzi:
            self.used_hanzi.clear()
            available_hanzi = hanzi_list.copy()
            
        self.current_hanzi = random.choice(available_hanzi)
        self.used_hanzi.add(self.current_hanzi)
        correct_pinyin = PINYIN_MAP[self.current_hanzi]
        
        # 生成错误选项
        # 生成相似错误选项（相同声母或韵母）
        correct = PINYIN_MAP[self.current_hanzi]
        initial = correct[0]  # 声母
        final = correct[1:]   # 韵母
        
        # 先初始化错误拼音列表
        wrong_pinyins = []
        
        # 筛选相似拼音（不含正确答案）
        similar = [v for k,v in PINYIN_MAP.items() 
                  if (v.startswith(initial) or v.endswith(final))
                  and v != correct]
        
        # 确保获得3个错误选项
        if len(similar) >= 3:
            wrong_pinyins = random.sample(similar, 3)
        else:
            # 补充随机错误选项
            other_pinyins = [v for k,v in PINYIN_MAP.items() 
                            if v not in similar and v != correct]
            needed = 3 - len(similar)
            wrong_pinyins = similar + random.sample(other_pinyins, needed)
        options = [correct_pinyin] + wrong_pinyins
        random.shuffle(options)
        
        # 更新界面
        self.hanzi_label.config(text=self.current_hanzi)
        for i, btn in enumerate(self.option_buttons):
            btn.config(text=options[i], state=tk.NORMAL)
        self.correct_index = options.index(correct_pinyin)
        self.current_question += 1

    def on_learning_window_close(self):
        self.learning_window.destroy()

    def show_history(self):
        history_window = tk.Toplevel(self.master)
        history_window.title("学习历史记录")
        
        # 创建表格框架
        tree = ttk.Treeview(history_window, columns=('时间', '单元', '得分'), show='headings')
        tree.heading('时间', text='测试时间')
        tree.heading('单元', text='学习单元')
        tree.heading('得分', text='得分/总分')
        tree.column('时间', width=300)
        tree.column('单元', width=200)
        tree.column('得分', width=150)
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(history_window, orient="vertical", command=tree.yview)
        tree.configure(yscrollcommand=scrollbar.set)
        
        # 填充数据
        for record in self.config['history_records']:
            tree.insert('', 'end', values=(
                record['timestamp'],
                record['unit'],
                f"{record['score']}/{record['total']}"
            ))
        
        # 布局组件
        tree.grid(row=0, column=0, sticky='nsew')
        scrollbar.grid(row=0, column=1, sticky='ns')
        
        # 配置窗口弹性布局
        history_window.rowconfigure(0, weight=1)
        history_window.columnconfigure(0, weight=1)
        
        # 设置窗口尺寸
        history_window.geometry("800x600")
        self.center_window()
        self.master.deiconify()
        
        # 恢复时重新居中
        self.master.update_idletasks()
        screen_width = self.master.winfo_screenwidth()
        screen_height = self.master.winfo_screenheight()
        window_width = self.master.winfo_reqwidth()
        window_height = self.master.winfo_reqheight()
        x = (screen_width // 2) - (window_width // 2)
        y = (screen_height // 2) - (window_height // 2)
        self.master.geometry(f"+{x}+{y}")

    def check_answer(self, selected_idx):
        if selected_idx == self.correct_index:
            self.score += 10
            self.create_custom_dialog("太棒了！", "正确")
        else:
            self.create_custom_dialog(f"正确答案是: {self.option_buttons[self.correct_index]['text']}", "错误")

    def create_custom_dialog(self, message, title):
        dialog = tk.Toplevel(self.learning_window)
        dialog.title(title)
        dialog.geometry("600x300+{}+{}".format(
            self.learning_window.winfo_x() + 200,
            self.learning_window.winfo_y() + 200
        ))
        
        ttk.Label(dialog, text=message, font=('Microsoft YaHei', 32), wraplength=500)\
            .pack(expand=True, padx=20, pady=20)
        
        btn = ttk.Button(dialog, text="确定", command=dialog.destroy,
                        style='Big.TButton')
        btn.pack(pady=20, ipadx=30, ipady=15)
        
        dialog.transient(self.learning_window)
        dialog.grab_set()
        dialog.wait_window(dialog)
        
        self.score_label.config(text=f"得分: {self.score}")
        self.next_question()

    def show_final_result(self):
        from datetime import datetime
        # 记录测试结果
        test_record = {
            'timestamp': datetime.now().isoformat(),
            'unit': self.unit_combobox.get(),
            'score': self.score,
            'total': self.total_questions * 10
        }
        # 确保历史记录字段存在
        if 'history_records' not in self.config:
            self.config['history_records'] = []
        self.config['history_records'].append(test_record)
        self.save_config()
        
        total_score = self.total_questions * 10
        comment = "优秀！" if self.score >= total_score*0.9 else "良好！" if self.score >= total_score*0.6 else "继续加油！"
        dialog = tk.Toplevel(self.learning_window)
        dialog.title("练习结果")
        dialog.geometry("600x300+{}+{}".format(
            self.learning_window.winfo_x() + 200,
            self.learning_window.winfo_y() + 200
        ))
        dialog.protocol("WM_DELETE_WINDOW", lambda: [dialog.destroy(), self.learning_window.destroy(), self.master.deiconify()])
        
        ttk.Label(dialog, text=f"总分: {self.score}\n评语: {comment}", font=('Microsoft YaHei', 32), wraplength=500)\
            .pack(expand=True, padx=20, pady=20)
        
        btn = ttk.Button(dialog, text="确定", command=lambda: [dialog.destroy(), self.learning_window.destroy(), self.master.deiconify()], style='Big.TButton')
        btn.pack(pady=20, ipadx=30, ipady=15)
        
        dialog.transient(self.learning_window)
        dialog.grab_set()
        dialog.wait_window(dialog)

if __name__ == "__main__":
    root = tk.Tk()
    app = ChineseLearningApp(root)
    root.mainloop()